package google.code.asoap.integration;

import google.code.asoap.annotation.SOAPService;
import google.code.asoap.util.SoapAnnotationDataCache;
import google.code.asoap.util.SoapAnnotationDataCache.ServiceInterfaceData;

import java.lang.reflect.Proxy;
import java.net.MalformedURLException;
import java.net.URL;

public final class ServiceFactory {

	private static final ServiceFactory instance = new ServiceFactory();
	
	private final ServiceInvocationHandler invocationHandler;
	
	private ServiceFactory() {
		invocationHandler = new ServiceInvocationHandler();
	}
	
	public static ServiceFactory getInstance() {
		return instance;
	}
	
	public Object newService(Class<?> serviceInterfaceType) throws MalformedURLException {
		if (!serviceInterfaceType.isInterface()) {
			throw new IllegalArgumentException("Invalid type argument. Proxy service instance are created based on interface types.");
		}
		final ServiceInterfaceData serviceData = SoapAnnotationDataCache.addServiceInterface(serviceInterfaceType);
		final URL url = serviceData.getServerUrl();
		if (url == null) {
			throw new MalformedURLException("Invalid server URL. Make sure that you set the [serverUrl] attribute from [" + SOAPService.class.getSimpleName() + "] annotation.");
		}
		return Proxy.newProxyInstance(ServiceFactory.class.getClassLoader(), new Class<?>[] { serviceInterfaceType }, this.invocationHandler);
	}

	public Object newService(Class<?> serviceInterfaceType, URL serverUrl) throws MalformedURLException {
		if (!serviceInterfaceType.isInterface()) {
			throw new IllegalArgumentException("Invalid type argument. Proxy service instance are created based on interface types.");
		}
		if (serverUrl == null) {
			throw new MalformedURLException("The server URL cannot be null.");
		}
		final ServiceInterfaceData serviceData = SoapAnnotationDataCache.addServiceInterface(serviceInterfaceType);
		serviceData.setServerUrl(serverUrl);
		return Proxy.newProxyInstance(ServiceFactory.class.getClassLoader(), new Class<?>[] { serviceInterfaceType }, this.invocationHandler);
	}

}
